<script>
  import { uploadImage, deleteImage } from '@/api/upload';
  import { toResult } from '@/utils/index';
  import { guid } from '@/utils/math';
  import * as otoUtils from '@/components/utils/index';

  export default {
    props: {
      uploadMoreStyle: {
        type: Object,
        default() {
          return {
            src: ''
          };
        }
      },
      // 最大图片上传数量
      max: {
        type: Number,
        default: 9
      },
      // 是否可以多选
      multiple: {
        type: Boolean,
        default: true
      },
      // 是否上传
      autoUpload: {
        type: Boolean,
        default: false
      },
      group: {
        type: String,
        default: ''
      },
      type: {
        type: Number,
        default: 1
      },
      dataList: {
        type: Array,
        default() {
          return [];
        }
      },
      count: {
        type: Number,
        default: 9
      },
      value: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        list: [] // item = { id,pictureId,saveStaus,uploadStatus,path } // uploadStatus有三种 uploading 正在上传 success 上传成功 fail 上传失败
      };
    },
    mounted() {
      this.$otoFormItem = otoUtils.$parent(this, 'OtoFormItem');
    },
    watch: {
      value: {
        handler() {
          if (this.$otoFormItem) {
            this.$otoFormItem.validate({ event: null, value: this.value });
          }
        }
      }
    },
    methods: {
      async retry(e) {
        console.log(this.list);
        const { item, index } = e.currentTarget.dataset;
        const { group, type } = this;
        const [err, res] = await toResult(
          uploadImage({
            filePath: item.path,
            params: { group, orders: index, type }
          })
        );
        if (err) {
          return console.log(err);
        }
        const { pictureId } = res.data;
        this.setPictureId(item, pictureId);
        console.log(this.list);
      },
      selectFile() {
        const { max, autoUpload, list, multiple, count } = this;
        uni.chooseImage({
          count: multiple ? count : 1,
          sourceType: ['album', 'camera'],
          sizeType: 'compressed',
          success: (chooseImageRes) => {
            const tempFilePaths = chooseImageRes.tempFilePaths.map((item) => {
              const _item = {};
              _item.id = guid();
              _item.saveStaus = 'local';
              if (autoUpload) {
                _item.uploadStatus = 'uploading';
              } else {
                _item.uploadStatus = 'not-upload';
              }
              _item.path = item;
              return _item;
            });
            console.log(tempFilePaths);
            if (list.concat(tempFilePaths).length > max) {
              return this.$message.warning(`您还能选择${max - list.length}张！`);
            }
            tempFilePaths.forEach((item) => {
              this.list.push(item);
            });
            if (autoUpload) {
              this.uploadFile(tempFilePaths);
            } else if (max === 1) {
              this.$emit('input', this.list[0].path);
              this.$emit('getImages', this.list);
            } else {
              this.$emit('input', this.list);
              this.$emit('getImages', this.list);
            }
          }
        });
      },
      async uploadFile(uploadList) {
        uni.showLoading({
          title: '上传中～',
          mask: true
        });
        const first = uploadList.shift();
        const { group } = this;
        const [err, res] = await toResult(
          uploadImage({
            filePath: first.path,
            params: { group, orders: this.getListIndex(first), type: this.type }
          })
        );
        if (err) {
          [first, ...uploadList].forEach((item) => {
            console.log(item);
            this.deleteImg('', item);
          });
          uni.hideLoading();
          return console.log(err);
        }
        const { pictureId, group: groupKey, path } = res.data;
        console.log(res);
        this.setPictureId(first, pictureId);

        if (uploadList.length > 0) {
          const resList = await this.uploadMore(uploadList, groupKey);
          console.log(resList);
          resList.forEach((res, index) => {
            if (res && res.code && res.code === 200) {
              const { pictureId } = res.data;
              this.setPictureId(uploadList[index], pictureId);
              console.log('success');
            } else {
              this.setPictureId(uploadList[index], '', 'fail');
              console.log('fail');
            }
          });
        }
        if (this.max > 1) {
          this.$emit('update:group', groupKey);
          this.$emit('input', groupKey);
        } else {
          this.$emit('update:group', groupKey);
          this.$emit('input', path);
        }
        this.$emit('update:dataList', this.list);
        uni.hideLoading();
        console.log(this.list);
      },
      setPictureId(first, pictureId, uploadStatus = 'success') {
        console.log(first);
        const firtIndex = this.list.findIndex((item) => item.id === first.id);
        console.log(firtIndex);
        this.$set(this.list[firtIndex], 'pictureId', pictureId);
        this.$set(this.list[firtIndex], 'uploadStatus', uploadStatus);
      },
      getListIndex(first) {
        return this.list.findIndex((item) => item.id === first.id);
      },
      uploadMore(uploadList, group) {
        const promises = uploadList.map((item) =>
          uploadImage({
            filePath: item.path,
            params: { group, orders: this.getListIndex(item), type: this.type }
          })
        );
        const len = promises.length;
        let count = 0;
        const resultList = [];
        return new Promise((resolve) => {
          promises.forEach((p, index) => {
            console.log(p);
            Promise.resolve(p)
              .then((result) => {
                count++;
                resultList[index] = result;
                if (count === len) {
                  resolve(resultList);
                }
              })
              .catch((e) => {
                count++;
                resultList[index] = e;
                if (count === len) {
                  resolve(resultList);
                }
              });
          });
        });
      },
      async deleteImage(item) {
        const { group } = this;
        const [err, res] = await uni.$oto.toResult(deleteImage(group, item.pictureId));
        if (err) {
          console.log(err);
        }
        console.log(res);
        this.$message.success('删除成功');
      },
      deleteImg(e, other = false) {
        let item = other;
        if (!other) {
          item = e.currentTarget.dataset.item;
        }
        try {
          if (this.autoUpload) {
            this.deleteImage(item);
          }
          const deleteIndex = this.list.findIndex((listItem) => {
            return item.id === listItem.id;
          });
          this.list.splice(deleteIndex, 1);
        } catch (error) {
          this.$message.success('删除失败');
        }
      },
      preview(e) {
        const { src } = e.currentTarget.dataset;
        const urls = this.list.map((item) => item.path);
        uni.previewImage({
          current: src,
          urls
        });
      }
    }
  };
</script>

<template>
  <view class="oto-image-upload">
    <view class="upload-list">
      <template v-for="(item, index) in list">
        <view class="upload-list-item upload-item-common" :key="index">
          <image class="image" :data-src="item.path" :src="item.path" mode="aspectFill" @click.stop="preview" />
          <image
            class="delete"
            src="/static/components/oto-image-upload/close.png"
            :data-item="item"
            @click.stop="deleteImg"
          />
          <view class="success" v-if="item.uploadStatus === 'success'">
            <view class="success-body">
              <view class="success-content"></view>
              <image class="success-icon" src="/static/components/oto-image-upload/upload-success.png" mode="" />
            </view>
          </view>
          <view class="uploading" v-if="item.uploadStatus === 'uploading'">上传中</view>
          <view
            class="retry"
            :data-item="item"
            :data-index="index"
            @click.stop="retry"
            v-if="item.uploadStatus === 'fail'"
            >点击重试</view
          >
        </view>
      </template>
      <view class="upload-more upload-item-common" @click.stop="selectFile" v-if="list.length !== max">
        <view class="upload-more-style" v-if="!uploadMoreStyle.src">
          <view class="transverse"></view>
          <view class="vertical"></view>
        </view>
        <image v-if="uploadMoreStyle.src" :src="uploadMoreStyle.src" mode="" />
      </view>
    </view>
  </view>
</template>

<style lang="scss" scoped>
  .oto-image-upload {
    .upload-list {
      margin-left: -12rpx;
      .upload-item-common {
        display: inline-block;
        width: 176rpx;
        height: 176rpx;
        padding: 0 0 12rpx 12rpx;
      }

      .upload-list-item {
        position: relative;

        .uploading {
          position: absolute;
          left: 12rpx;
          right: 0;
          bottom: 12rpx;
          color: #fff;
          background-color: forestgreen;
          font-size: 20rpx;
          padding: 8rpx 0;
          text-align: center;
          position: absolute;
        }

        .retry {
          position: absolute;
          left: 12rpx;
          right: 0;
          bottom: 12rpx;
          color: #fff;
          background-color: #fa3534;
          font-size: 20rpx;
          padding: 8rpx 0;
          text-align: center;
          position: absolute;
        }
        .image {
          width: 100%;
          height: 100%;
        }
        .delete {
          position: absolute;
          width: 32rpx;
          height: 32rpx;
          top: -12rpx;
          right: -10rpx;
        }
        .success {
          position: absolute;
          top: 0rpx;
          left: 12rpx;
          .success-body {
            position: relative;
            .success-content {
              width: 0;
              height: 0;
              border-top: 50rpx solid forestgreen;
              border-right: 50rpx solid transparent;
            }
            .success-icon {
              width: 32rpx;
              height: 32rpx;
              position: absolute;
              top: 0;
            }
          }
        }
      }
    }

    .upload-more {
      opacity: 1;

      .upload-more-style {
        display: inline-block;
        background: #ededed;
        position: relative;
        width: 100%;
        height: 100%;

        // 横
        .transverse {
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
          width: 109rpx;
          height: 5rpx;
          border-radius: 8rpx;
          opacity: 1;
          background: rgba(218.88, 218.88, 218.88, 1);
        }

        // 竖
        .vertical {
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
          width: 5rpx;
          height: 109rpx;
          border-radius: 8rpx;
          opacity: 1;
          background: rgba(218.88, 218.88, 218.88, 1);
        }
      }
    }
  }
</style>
